package cn.youfule.mecs.netty.protocol;


import cn.youfule.mecs.netty.MecsProtocol;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public abstract class AbstractHandler<I extends AbstractProtocolContext,O extends AbstractProtocolContext> {

    /**
     * 是否支持该Protocol
     * @param prot
     * @return
     */
    public boolean isSupport(MecsProtocol<I> prot){
        //获取功能码
        int functionCode = prot.getFunctionCode();
        for (byte fc: this.supportFunctionCode()){
            if(functionCode == fc){
                return true;
            }
        }
        return false;
    }

    /**
     * 支持的功能码
     * @return
     */
    protected abstract byte[] supportFunctionCode();

    /**
     * 通道数据读取
     * @param ctx
     * @param inbound
     * @throws Exception
     */
    public void channelRead(ChannelHandlerContext ctx, MecsProtocol<I> inbound) throws Exception{
        //进行数据处理
        this.process(ctx,inbound);
        //构造应答内容
        MecsProtocol<O> outbound = this.outboundBuild(ctx,inbound);
        if(outbound != null) {
            ctx.writeAndFlush(outbound);
//        channelHandlerContext.fireChannelRead(inbound);
        }
    }

    /**
     * 数据处理
     * @param ctx
     * @param inbound
     * @throws Exception
     */
    protected void process(ChannelHandlerContext ctx,MecsProtocol<I> inbound) throws Exception{

    }

    /**
     * 构建应答数据
     * @param ctx
     * @param inbound
     * @return
     * @throws Exception
     */
    protected MecsProtocol<O> outboundBuild(ChannelHandlerContext ctx, MecsProtocol<I> inbound) throws Exception{
//        Class<O> clazz = (Class<O>) ReflectionUtil.getTypeArgumentClassList(this.getClass(),1);
//        O outbound = clazz.newInstance();
        MecsProtocol<O> outbound = new MecsProtocol<>();
        outbound.setId(inbound.getId());
        outbound.setFactory(inbound.getFactory());
        outbound.setType(inbound.getType());
        outbound.setFunctionCode(inbound.getFunctionCode());
        outbound.setContext(this.outboundContextBuild(ctx,inbound,outbound));
        return outbound;
    }

    /**
     * 应答数据内容部分
     * @param ctx
     * @param inbound
     * @param outbound
     */
    protected O outboundContextBuild(ChannelHandlerContext ctx, MecsProtocol<I> inbound,MecsProtocol<O> outbound) throws Exception {
//        outbound.setStartIndex((byte) 0);
//        outbound.setContextLength((byte) 0);
        return null;
    }

}
